#include <iostream>
#include <fstream>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <thread>
#include <chrono>
#include <string>
#pragma comment(lib, "ws2_32.lib")

using namespace std;

string serial;
string client_id;
bool running = true;

void heartbeat(SOCKET sock) {
    while (running) {
        this_thread::sleep_for(30min);
        string msg = "HEARTBEAT:" + client_id + ":" + serial;
        send(sock, msg.c_str(), msg.size(), 0);

        char buf[256];
        if (recv(sock, buf, sizeof(buf), 0) <= 0) {
            cerr << "Connection lost\n";
            running = false;
            return;
        }
    }
}

int main() {
    ifstream config("client.config");
    if (config) {
        getline(config, serial);
    }
    else {
        cout << "Enter license serial: ";
        cin >> serial;
        ofstream("client.config") << serial;
    }

    WSADATA wsa;
    WSAStartup(MAKEWORD(2, 2), &wsa);

    SOCKET sock = socket(AF_INET, SOCK_STREAM, 0);
    sockaddr_in addr{};
    addr.sin_family = AF_INET;
    inet_pton(AF_INET, "127.0.0.1", &addr.sin_addr);
    addr.sin_port = htons(12345);

    if (connect(sock, (sockaddr*)&addr, sizeof(addr)) == SOCKET_ERROR) {
        cerr << "Connection failed\n";
        return 1;
    }

    string auth_msg = "AUTH:" + serial;
    send(sock, auth_msg.c_str(), auth_msg.size(), 0);

    char response[256];
    int bytes = recv(sock, response, sizeof(response), 0);
    if (bytes <= 0) {
        cerr << "Auth failed\n";
        return 1;
    }

    string resp_str(response, bytes);
    if (resp_str.find("SUCCESS") == string::npos) {
        cerr << "Auth failed: " << resp_str << endl;
        return 1;
    }

    client_id = resp_str.substr(resp_str.find_last_of(':') + 1);
    cout << "Authorization successful. Client ID: " << client_id << endl;

    thread hb_thread(heartbeat, sock);

    cout << "Press enter to exit...\n";
    cin.get();
    running = false;
    hb_thread.join();

    string exit_msg = "EXIT:" + client_id;
    send(sock, exit_msg.c_str(), exit_msg.size(), 0);
    closesocket(sock);
    WSACleanup();
    return 0;
}